﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;

namespace CommonUtils
{ /// <summary>
  /// custom log
  /// </summary>
  /// <example>
  ///    var log = new Log("Application");
  ///    log.I("startup");
  /// </example>
    public class Log
    {
        #region constant values
        const string _logLineFormat = "{0}|{1}|{2}|{3}|{4}";
        const string formatTimeWithMilliSecond = "yyyyMMdd HH:mm:ss fff";
        #endregion

        #region family fields
        string _tag = string.Empty;
        bool _isEnable = true;
        Log4netWrapper _log4net = null;
        #endregion

        #region constructor 
        /// <summary>
        /// 
        /// </summary>
        /// <param name="tag">always use for one class</param>
        /// <param name="isEnable">enbale ouput or not</param>
        /// <param name="log4net">Log4netWrapper</param>
        public Log(string tag, bool isEnable = true, Log4netWrapper log4net = null)
        {
            _tag = tag;
            _isEnable = isEnable;
            _log4net = log4net;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="tag">always use for one class</param> 
        /// <param name="log4net">Log4netWrapper</param>
        public Log(string tag, Log4netWrapper log4net = null)
        {
            _tag = tag;
            _isEnable = true;
            _log4net = log4net;
        }


        public Log(string tag)
        {
            _tag = tag;
            _isEnable = true;
            _log4net = null;
        }
        #endregion

        #region public methods
        public void I(string format, params object[] args)
        {
            if (!_isEnable) return;
            Write(_tag, LogLevels.I, format, args);
        }

        public void E(string format, params object[] args)
        {
            if (!_isEnable) return;
            Write(_tag, LogLevels.E, format, args);
        }

        public void E(Exception ex)
        {
            if (!_isEnable) return;
            Write(_tag, LogLevels.E, ex.ToString());
        }


        public void W(string format, params object[] args)
        {
            if (!_isEnable) return;
            Write(_tag, LogLevels.W, format, args);
        }

        public void F(string format, params object[] args)
        {
            if (!_isEnable) return;
            Write(_tag, LogLevels.F, format, args);
        }
        #endregion

        #region private methods

        void Write(string tag, LogLevels logLevel, string format, params object[] args)
        {
            if (logLevel < LogConfigure.LogLevel)
                return;
            try
            {
                if (args == null) return;
                for (int i = 0; i < args.Length; i++)
                {
                    if (args[i] == null)
                        args[i] = "Null";

                    //if (args[i].ToString().Length > 1000)
                    //    args[i] = args[i].ToString().Substring(0, 1000) + "...";
                }

                string logStr = string.Empty;
                if (format.Contains("{0}"))
                {
                    try
                    {
                        logStr = string.Format(format, args);
                    }
                    catch
                    {

                    }
                }
                else
                {
                    logStr = format;
                }
                logStr = logStr.Trim();
                if (!string.IsNullOrEmpty(logStr))
                {
                    string content = string.Format(_logLineFormat,
                    DateTime.Now.ToString(formatTimeWithMilliSecond), logLevel, Thread.CurrentThread.ManagedThreadId, tag, logStr);
                    //Trace.WriteLine(content);
                    if (LogConfigure.IsOutputToFile)
                    {
                        if (_log4net == null)
                        {
                            _log4net = Log4netWrapper.Default;
                        }
                        _log4net.Info(content);
                    }
                }
            }
            catch (Exception ex)
            {
                Trace.Write(ex);
            }
        }
        #endregion
    }
}
